package com.duke.payphone;

import java.io.Serializable;
import java.util.List;
import java.util.Map;

import org.xmlrpc.android.XMLRPCClient;
import org.xmlrpc.android.XMLRPCException;

import android.os.StrictMode;

import com.duke.payphone.factory.MapFactory;


/**
 * class used to convert maps into strings/bits .. and send it out using xml
 * 
 * IMPORTANT: - function = function name - result = valid or invalid - THE
 * SERVER SHOULD CHECK THAT ALL REQUIRED FIELDS ARE PRESENT BEFORE PROCESSING
 * REQUEST
 * 
 * 
 * @author Michael, Derek
 * 
 */
public class ServerPortal {
    private static final XMLRPCClient client = new XMLRPCClient("http://ec2-50-16-47-119.compute-1.amazonaws.com:8000");

    /**
     * 
     * call this method to send the server a map and get the server's response
     * server will respond with a map
     * 
     * @param message
     * @return
     */
    public static Map<String, Serializable> contactServer (Map<String, Serializable> message) {
    	StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build();

    	StrictMode.setThreadPolicy(policy); 
    	
        Map<String, Serializable> response = null;
        String function = (String) message.get("function");

        if (function.equalsIgnoreCase("login")) {
            response = loginHandler(message);
        }
        else if (function.equalsIgnoreCase("newuser")) {
            response = newuserHandler(message);
        }
        else if (function.equalsIgnoreCase("edituser")) {
            response = edituserHandler(message);
        }
        else if (function.equalsIgnoreCase("getuser")) {
            response = getuserHandler(message);
        }
        else if (function.equalsIgnoreCase("cardlist")) {
            response = cardlistHandler(message);
        }
        else if (function.equalsIgnoreCase("newcard")) {
            response = newcardHandler(message);
        }
        else if (function.equalsIgnoreCase("editcard")) {
            response = editcardHandler(message);
        }
        else if (function.equalsIgnoreCase("getcard")) {
            response = getcardHandler(message);
        }
        else if (function.equalsIgnoreCase("deletecard")) {
            response = deletecardHandler(message);
        }
        else if (function.equalsIgnoreCase("sellnew")) {
            response = sellnewHandler(message);
        }
        else if (function.equalsIgnoreCase("sellpoll")) {
            response = sellpollHandler(message);
        }
        else if (function.equalsIgnoreCase("buynew")) {
            response = buynewHandler(message);
        }
        else if (function.equalsIgnoreCase("buyyes")) {
            response = buyyesHandler(message);
        }
        else if (function.equalsIgnoreCase("sellcomplete")) {
            response = sellcompleteHandler(message);
        }
        else {
            System.out.println("ERROR: FUNCTION HANDLER DOES NOT EXIST");
        }

        System.out.println("Executed function: " + (String) message.get("function"));
        System.out.println(message);

        return response;
    }

    /**
     * LOGIN App transmits keys: function, sessionid, username, password
     * 
     * App expects keys: server, session (DN), result, sessionid*, username*
     * 
     * @param message
     * @return
     */
    private static Map<String, Serializable> loginHandler (Map<String, Serializable> message) {
    	Map<String, Serializable> response = MapFactory.createReceiveMap();
        try {
        	// 1. send map to server 
        	@SuppressWarnings("unchecked")
        	Map<String, Serializable> result = (Map<String, Serializable>) client.call("login", 
        			message.get("sessionid"), 
        			message.get("username"), 
        			message.get("password"));
        	
        	// 2. get response from server 

            // 3. convert server response into map (with expected keys [see above])
        	response.put("server", result.get("server"));
            response.put("session", result.get("session"));
            response.put("result", result.get("result"));
            response.put("sessionid", result.get("sessionid"));
            response.put("username", message.get("username"));
        }
        catch (XMLRPCException e) {
            e.printStackTrace();
        }
        
        return response;
    }

    /**
     * NEWUSER App transmits keys: function, sessionid, username, password,
     * firstname, lastname
     * 
     * App expects keys: server, session (DN), result, sessionid*, username*
     * 
     * Note: if newuser creation is successful, app will auto login (bypass
     * login screen) -> server needs to return a new sessionid
     * 
     * @param message
     * @return
     */
    private static Map<String, Serializable> newuserHandler (Map<String, Serializable> message) {
        Map<String, Serializable> response = MapFactory.createReceiveMap();
        try {
        	// 1. send map to server 
        	@SuppressWarnings("unchecked")
        	Map<String, Serializable> result = (Map<String, Serializable>) client.call("create_account", message.get("sessionid"),
                    message.get("username"),
                    message.get("password"),
                    message.get("firstname"),
                    message.get("lastname"));
        	
        	// 2. get response from server 

            // 3. convert server response into map (with expected keys [see above])
        	response.put("server", result.get("server"));
            response.put("session", result.get("session"));
            response.put("result", result.get("result"));
            response.put("sessionid", result.get("sessionid"));
            response.put("username", message.get("username"));
        }
        catch (XMLRPCException e) {
            e.printStackTrace();
        }
        
        return response;
    }

    /**
     * EDITUSER App transmits keys: function, sessionid, username, password,
     * firstname, lastname
     * 
     * App expects keys: server, session, result
     * 
     * @param message
     * @return
     */
    private static Map<String, Serializable> edituserHandler (Map<String, Serializable> message) {
    	Map<String, Serializable> response = MapFactory.createReceiveMap();
        try {
        	// 1. send map to server 
        	@SuppressWarnings("unchecked")
        	Map<String, Serializable> result = (Map<String, Serializable>) client.call("update_account", message.get("sessionid"),
                    message.get("username"),
                    message.get("password"),
                    message.get("firstname"),
                    message.get("lastname"));
        	
        	// 2. get response from server 

            // 3. convert server response into map (with expected keys [see above])
        	response.put("server", result.get("server"));
            response.put("session", result.get("session"));
            response.put("result", result.get("result"));
        }
        catch (XMLRPCException e) {
            e.printStackTrace();
        }
        
        return response;
    }

    /**
     * GETUSER App transmits keys: function, sessionid, username
     * 
     * App expects keys: server, session, result, username, password, firstname,
     * lastname
     * 
     * @param message
     * @return
     */
    private static Map<String, Serializable> getuserHandler (Map<String, Serializable> message) {
    	Map<String, Serializable> response = MapFactory.createReceiveMap();
        try {
        	// 1. send map to server
        	@SuppressWarnings("unchecked")
        	Map<String, Serializable> result = (Map<String, Serializable>) client.call("get_account", 
        			message.get("sessionid"),
                    message.get("username"));
        	
        	// 2. get response from server 
        	Object[] data = (Object[]) result.get("data");

            // 3. convert server response into map (with expected keys [see above])
        	response.put("server", result.get("server"));
            response.put("session", result.get("session"));
            response.put("result", result.get("result"));
            response.put("username", data[0].toString());
            response.put("password", data[1].toString());
            response.put("firstname", data[2].toString());
            response.put("lastname", data[3].toString());
        }
        catch (XMLRPCException e) {
            e.printStackTrace();
        }
        
        return response;
    }

    /**
     * CARDLIST App transmits keys: function, sessionid, username
     * 
     * App expects keys: server, session, result, cardlist
     * 
     * Note: cardlist is a string array
     * 
     * @param message
     * @return
     */
    private static Map<String, Serializable> cardlistHandler (Map<String, Serializable> message) {
    	Map<String, Serializable> response = MapFactory.createReceiveMap();
        try {
        	// 1. send map to server 
        	@SuppressWarnings("unchecked")
        	Map<String, Serializable> result = (Map<String, Serializable>) client.call("get_credit_list", 
        			message.get("sessionid"),
                    message.get("username"));
        	
        	// 2. get response from server 
        	Object[] full_cc_list = (Object[]) result.get("data");
        	String[] data = new String[full_cc_list.length];
        	for(int i = 0; i < full_cc_list.length; i++)
        	{
        		Object[] temp = (Object[]) full_cc_list[i];
        		data[i] = temp[0].toString();
        	}

            // 3. convert server response into map (with expected keys [see above])
        	response.put("server", result.get("server"));
            response.put("session", result.get("session"));
            response.put("result", result.get("result"));
            response.put("cardlist", data);
        }
        catch (XMLRPCException e) {
            e.printStackTrace();
        }
        
        return response;
    }

    /**
     * NEWCARD App transmits keys: function, sessionid, username, cardnumber,
<<<<<<< HEAD
     * expdate, name, address1, address2, city, state, zip
=======
     * expdate,
     * name, address1, address2, city, state, zip
>>>>>>> michael2
     * 
     * App expects keys: server, session, result
     * 
     * @param message
     * @return
     */
    private static Map<String, Serializable> newcardHandler (Map<String, Serializable> message) {
    	Map<String, Serializable> response = MapFactory.createReceiveMap();
        try {
        	// 1. send map to server 
        	@SuppressWarnings("unchecked")
        	Map<String, Serializable> result = (Map<String, Serializable>) client.call("create_credit_card", 
					message.get("sessionid"),
                    message.get("username"),
                    message.get("cardnumber"),
                    message.get("expdate"),
                    message.get("name"),
                    message.get("address1"), 
                    message.get("address2"),
                    message.get("city"),
                    message.get("state"), 
                    message.get("zip"));
        	
        	// 2. get response from server 

            // 3. convert server response into map (with expected keys [see above])
        	response.put("server", result.get("server"));
            response.put("session", result.get("session"));
            response.put("result", result.get("result"));
        }
        catch (Exception e) {
            e.printStackTrace();
        }
        
        return response;
    }

    /**
     * EDITCARD App transmits keys: function, sessionid, username, cardnumber,
<<<<<<< HEAD
     * expdate, name, address1, address2, city, state, zip
=======
     * expdate,
     * name, address1, address2, city, state, zip
>>>>>>> michael2
     * 
     * App expects keys: server, session, result
     * 
     * @param message
     * @return
     */
    private static Map<String, Serializable> editcardHandler (Map<String, Serializable> message) {
    	Map<String, Serializable> response = MapFactory.createReceiveMap();
        try {
        	// 1. send map to server 
        	@SuppressWarnings("unchecked")
        	Map<String, Serializable> result = (Map<String, Serializable>) client.call("update_credit_card", 
					message.get("sessionid"),
                    message.get("username"),
                    message.get("cardnumber"),
                    message.get("expdate"),
                    message.get("name"), 
                    message.get("address1"), 
                    message.get("address2"),
                    message.get("city"),
                    message.get("state"), 
                    message.get("zip"));
        	
        	// 2. get response from server 

            // 3. convert server response into map (with expected keys [see above])
        	response.put("server", result.get("server"));
            response.put("session", result.get("session"));
            response.put("result", result.get("result"));
        }
        catch (XMLRPCException e) {
            e.printStackTrace();
        }
        
        return response;
    }

    /**
     * GETCARD App transmits keys: function, sessionid, username, cardnumber
     * 
     * App expects keys: server, session, result, cardnumber, expdate, name,
     * address1, address2, city, state, zip
     * 
     * @param message
     * @return
     */
    private static Map<String, Serializable> getcardHandler (Map<String, Serializable> message) {
    	Map<String, Serializable> response = MapFactory.createReceiveMap();
        try {
        	// 1. send map to server 
        	@SuppressWarnings("unchecked")
        	Map<String, Serializable> result = (Map<String, Serializable>) client.call("get_credit_card", 
					message.get("sessionid"),
                    message.get("username"),
                    message.get("cardnumber"));
        	
        	// 2. get response from server 
        	Object[] data = (Object[]) result.get("data");

            // 3. convert server response into map (with expected keys [see above])
        	response.put("server", result.get("server"));
            response.put("session", result.get("session"));
            response.put("result", result.get("result"));
            response.put("cardnumber", data[1].toString());
            response.put("expdate", data[2].toString());
            response.put("name", data[3].toString());
            response.put("address1", data[4].toString());
            response.put("address2", data[5].toString());
            response.put("city", data[6].toString());
            response.put("state", data[7].toString());
            response.put("zip", data[8].toString());
        }
        catch (XMLRPCException e) {
            e.printStackTrace();
        }
        
        return response;
    }

    /**
     * DELETECARD App transmits keys: function, sessionid, username, cardnumber
     * 
     * App expects keys: server, session, result
     * 
     * @param message
     * @return
     */
    private static Map<String, Serializable> deletecardHandler (Map<String, Serializable> message) {
    	Map<String, Serializable> response = MapFactory.createReceiveMap();
        try {
        	// 1. send map to server 
        	@SuppressWarnings("unchecked")
        	Map<String, Serializable> result = (Map<String, Serializable>) client.call("delete_credit_card", 
					message.get("sessionid"),
                    message.get("username"),
                    message.get("cardnumber"));
        	
        	// 2. get response from server 

            // 3. convert server response into map (with expected keys [see above])
        	response.put("server", result.get("server"));
            response.put("session", result.get("session"));
            response.put("result", result.get("result"));
        }
        catch (XMLRPCException e) {
            e.printStackTrace();
        }
        
        return response;
    }

    /**
     * SELLNEW App transmits keys: function, sessionid, username, productname,
     * price, date
     * 
<<<<<<< HEAD
     * App expects keys: server, session, result, qrcode (byte array of image)
=======
     * App expects keys: server, session, result, qrcode
>>>>>>> michael2
     * 
     * Note: qrcode is an image
     * 
     * @param message
     * @return
     */
    private static Map<String, Serializable> sellnewHandler (Map<String, Serializable> message) {
    	Map<String, Serializable> response = MapFactory.createReceiveMap();
        try {
        	// 1. send map to server
        	@SuppressWarnings("unchecked")
        	Map<String, Serializable> result = (Map<String, Serializable>) client.call("create_trans", 
					message.get("sessionid"),
                    message.get("username"),
                    message.get("productname"),
                    message.get("price"), 
                    message.get("date"));
        	
        	byte[] qrcode = (byte[]) client.call("generate_qr", message.get("username"));
        	// 2. get response from server 

            // use Drawable qrcode = Drawable.createFromXml(xmlstuff);

            // 3. convert server response into map (with expected keys [see above])
            response.put("server", result.get("server"));
            response.put("session", result.get("session"));
            response.put("result", result.get("result"));
            response.put("qrcode", qrcode);
        }
        catch (XMLRPCException e) {
            e.printStackTrace();
        }
        
        return response;
    }

    /**
     * SELLPOLL App transmits keys: function, sessionid, username
     * 
     * App expects keys: server, session, result, productname, price, date,
     * seller, buyer
     * 
     * NOte: the SERVER MUST TIME OUT FIRST (to ensure that transactions either
     * work or don't) - user's sessionid can only be linked to one transaction
     * at once
     * 
     * @param message
     * @return
     */
    private static Map<String, Serializable> sellpollHandler (Map<String, Serializable> message) {
    	Map<String, Serializable> response = MapFactory.createReceiveMap();
        try {
        	// 1. send map to server 
        	@SuppressWarnings("unchecked")
        	Map<String, Serializable> result = (Map<String, Serializable>) client.call("get_trans", 
					message.get("sessionid"),
                    message.get("username"));
        	
        	// 2. get response from server 
        	Object[] data = (Object[]) result.get("data");

            // 3. convert server response into map (with expected keys [see above])
            response.put("server", result.get("server"));
            response.put("session", result.get("session"));
            response.put("result", result.get("result"));
            if(data != null)
            {
                response.put("seller", data[1].toString());
                response.put("buyer", data[2].toString());
                response.put("price", data[3].toString());
                response.put("date", data[4].toString());
                response.put("productname", data[5].toString());
            }
        }
        catch (XMLRPCException e) {
            e.printStackTrace();
        }
        
        return response;
    }

    /**
     * BUYNEW App transmits keys: function, sessionid, username, decodedid (tid)
     * 
     * App expects keys: server, session, result, productname, price, date,
     * seller
     * 
     * @param message
     * @return
     */
    private static Map<String, Serializable> buynewHandler (Map<String, Serializable> message) {
    	Map<String, Serializable> response = MapFactory.createReceiveMap();
        try {
        	// 1. send map to server
        	@SuppressWarnings("unchecked")
			Map<String, Serializable> result = (Map<String, Serializable>) client.call("update_trans_with_buyer", 
					message.get("sessionid"), 
                    message.get("decodedid"),
                    message.get("username"));
        	
        	// 2. get response from server 
        	Object[] data = (Object[]) result.get("data");
        	
            // 3. convert server response into map (with expected keys [see above])
        	response.put("server", result.get("server"));
            response.put("session", result.get("session"));
            response.put("result", result.get("result"));
            if(data != null)
            {
                response.put("seller", data[1].toString());
                response.put("buyer", data[2].toString());
                response.put("price", data[3].toString());
                response.put("date", data[4].toString());
                response.put("productname", data[5].toString());
            }
        }
        catch (XMLRPCException e) {
            e.printStackTrace();
        }
        
        return response;
    }

    /**
     * BUYYES App transmits keys: function, sessionid, username, cardnumber
     * 
     * App expects keys: server, session, result, productname, price, date,
     * seller, buyer
     * 
     * Note: sessionid of the buyer should be linked to the transaction
     * 
     * @param message
     * @return
     */
    private static Map<String, Serializable> buyyesHandler (Map<String, Serializable> message) {
    	Map<String, Serializable> response = MapFactory.createReceiveMap();
        try {
        	// 1. send map to server 
        	@SuppressWarnings("unchecked")
        	Map<String, Serializable> result = (Map<String, Serializable>) client.call("complete_trans", 
					message.get("sessionid"),
                    message.get("username"), 
                    message.get("cardnumber"));
        	
        	// 2. get response from server 
        	Object[] data = (Object[]) result.get("data");
        	
            // 3. convert server response into map (with expected keys [see above])
            response.put("server", result.get("server"));
            response.put("session", result.get("session"));
            response.put("result", result.get("result"));
            response.put("seller", data[1].toString());
            response.put("buyer", data[2].toString());
            response.put("price", data[3].toString());
            response.put("date", data[4].toString());
            response.put("productname", data[5].toString());
        }
        catch (XMLRPCException e) {
            e.printStackTrace();
        }
        
        return response;
    }
    
    
    
    
    /**
     * SELLCOMPLETE 
     * 
     * 
     * @param message
     * @return
     */
    private static Map<String, Serializable> sellcompleteHandler (Map<String, Serializable> message) {
        Map<String, Serializable> response = MapFactory.createReceiveMap();
        try {
                // 1. send map to server 
                @SuppressWarnings("unchecked")
                Map<String, Serializable> result = (Map<String, Serializable>) client.call("sell_complete", 
                                        message.get("sessionid"),
                    message.get("username"));
                
                // 2. get response from server 
//                Object[] data = (Object[]) result.get("data");
                
            // 3. convert server response into map (with expected keys [see above])
            response.put("server", result.get("server"));
            response.put("session", result.get("session"));
            response.put("result", result.get("result"));
//            response.put("seller", data[1].toString());
//            response.put("buyer", data[2].toString());
//            response.put("price", data[3].toString());
//            response.put("date", data[4].toString());
//            response.put("productname", data[5].toString());
        }
        catch (XMLRPCException e) {
            e.printStackTrace();
        }
        
        return response;
    }
    
    
    

}
